#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <cerrno>
using namespace std;


class TcpSever
{
  private:
    int _sockfd;
    int _port;
  public:
    void Init()
    {
      _sockfd = socket(AF_INET, SOCK_STREAM , 0);
      if (_sockfd < 0)
      {
        cout << "socket error" << endl;
        exit(2);
      }

      struct sockaddr_in local;
      memset(&local , 0 , sizeof(local));
      local.sin_family = AF_INET;
      local.sin_port = htons(_port);
      local.sin_addr.s_addr = INADDR_ANY;
      if(bind(_sockfd , (struct sockaddr*)&local , sizeof(sockaddr)) < 0)
      {
        cout << "bind error" << endl;
        exit(3);
      }

      if(listen(_sockfd , 5) < 0)
      {
        cout << "listen error" << endl;
        exit(4);
      }
    }
    void Service(int sock)
    {
      char buff[1024];
      while(true)
      {
        ssize_t size = read(sock , buff , sizeof(buff)-1);
        if (size > 0)
        {
          buff[size] = 0; 
          write(sock , buff , size);
        }
        else if (size == 0) // 对端关闭
        {
          cout << "read cloes " << endl;
          break;
        }
        else 
        {
          cout << "error : " << errno  << endl;
          break;
        }
      }
       close(sock);
    }
    void Start()
    {
      for(;;)
      {
        struct sockaddr_in peer;
        memset(&peer , 0 , sizeof(peer)); 
        socklen_t len = sizeof(peer);
        int sock = accept(_sockfd , (struct sockaddr*)&peer , &len);
        if (sock < 0)
        {
          cout << "accept error" << endl;
          sleep(10);
          continue; // do not stop server 
        }

        string client_ip = inet_ntoa(peer.sin_addr);
        int client_port = ntohs(peer.sin_port);
        cout << "get a new link " << sock <<  "new port is " << client_port <<endl ;

        Service(sock);
      }
    }
  public:
    TcpSever(int port)
      :_sockfd(-1),
      _port(port)
    {}
    ~TcpSever()
    {
      if (_sockfd > 0)
      {
         close(_sockfd);
      }
    }
};


int main(int argc , char* argv[])
{
  if (argc != 2)
  {
    cout << "Usage" << argv[0] << "prot" << endl;
    exit(1);
  }

  int port = atoi(argv[1]);
  auto* sur = new TcpSever(port);
  sur->Init();
  sur->Start();
  return 0;
}
